package cn.ljy.authority.config.security.sms;

import cn.ljy.authority.model.SysUser;
import cn.ljy.authority.service.impl.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

/**
 * 定义自定义的认证提供者，用于手机短信验证码登录业务的验证
 * 规格：
 * 1.在使用短信验证时，调用SmsCodeAuthenticationFilter过滤器将参数封装成SmsCodeAuthenticationToken类（含获取手机号码和验证码）
 * 2.根据supports函数中的参数判断，判断传入的认证令牌是否为SmsCodeAuthenticationToken的子类，如果是则调用本业务处理器
 */
@Component
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private ISysUserService userService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SmsCodeAuthenticationToken smsToken = (SmsCodeAuthenticationToken) authentication;
        String mobile = (String) smsToken.getPrincipal();
        String code = (String) smsToken.getCredentials();
        try{
            //1.根据手机号码和验证码进行登录，相当于验证
            SysUser sysUser = userService.loginFromTel(mobile, code);
            //2.如果登录成功，则返回已认证的令牌
            UserDetails userDetails = userService.loadUserByUsername(sysUser.getUsername());
//            if (userDetails == null) {
//                throw new AuthenticationServiceException("该手机号未注册");
//            }
            // 创建已认证成功的令牌
            SmsCodeAuthenticationToken authenticatedToken = new SmsCodeAuthenticationToken(
                    userDetails,
                    code,
                    userDetails.getAuthorities()
            );
            authenticatedToken.setDetails(smsToken.getDetails());
            return authenticatedToken;
        }catch (Exception e){
            //验证码登错误信息在这里捕获，并返回错误信息给前端
            throw new AuthenticationServiceException(e.getMessage());
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        //判断传入的认证令牌是否为SmsCodeAuthenticationToken的子类,只有子类才能进行验证
        return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

